#include <QString>
#include <QDomDocument>
#include <QDomElement>
#include <QFile>
#include <QDir>
#include <QApplication>
#include <QTextStream>
#include <QRegExp>
#include <QDateTime>
#include <QBitArray>
#include <QDebug>
#include <QProcess>
#include <QXmlQuery>

#include "fileutilities.h"
#include "directoryutilities.h"
#include "settings.h"

#include "common/fstraverseiterator.h"

FileUtilities::FileUtilities(GeneratorOutputView &outputView, GeneratorData &generatorData) :
		m_outputView(outputView), m_generatorData(generatorData)
{
	m_infoPlistFileNameNoSpaces = m_generatorData.infoPlistValue(INFO_PLIST_KEY_DISPLAY_NAME);
	m_infoPlistFileNameNoSpaces.replace(" ", "_");
}

bool FileUtilities::updateMainFile()
{
        // OBS QString mainFileName = m_generatorData.projectDirectory() + MAIN_FILE;
    QString
        mainFileName = m_generatorData.srcDirectory() + MAIN_FILE;
	QFile projectTemplateFileIn(mainFileName);
	if(!projectTemplateFileIn.open(QIODevice::ReadOnly | QIODevice::Text)) {
		QString errMsg = QString(ERR_FILE_OPEN_READ_FAILED_CANNOT_CONTINUE).arg(MAIN_FILE);
		m_outputView.printOutput(errMsg);
		return false;
	}
	QTextStream streamIn(&projectTemplateFileIn);
	QString templateFileContent(streamIn.readAll());
	projectTemplateFileIn.close();

	if(templateFileContent.contains(FULL_SCREEN_TAG)) {
		templateFileContent.replace(FULL_SCREEN_TAG, Settings::get(Settings::ShowFullScreen).toBool() ? "1" : "0");
	}

	if(templateFileContent.contains(SOFT_KEYS_TAG)) {
		templateFileContent.replace(SOFT_KEYS_TAG, Settings::get(Settings::ShowSoftKeys).toBool() ? "1" : "0");
	}

	QFile mainFileOut(mainFileName);
	if(!mainFileOut.open(QIODevice::WriteOnly | QIODevice::Text)) {
		QString errMsg = QString(ERR_FILE_OPEN_WRITE_FAILED_CANNOT_CONTINUE).arg(MAIN_FILE);
		m_outputView.printOutput(errMsg);
		return false;
	}

	QTextStream streamOut(&mainFileOut);
	streamOut << templateFileContent;
	mainFileOut.close();

	QString msg = QString(MSG_FILE_UPDATED_SUCCESSFULLY).arg(MAIN_FILE);
	m_outputView.printOutput(msg);

	return true;
}

bool FileUtilities::updateMainWindowFile()
{
        // OBS QString mainWindowFileName = m_generatorData.projectDirectory() + MAIN_WINDOW_FILE;
    QString
        mainWindowFileName = m_generatorData.srcDirectory() + MAIN_WINDOW_FILE;
	QFile projectTemplateFileIn(mainWindowFileName);
	if (!projectTemplateFileIn.open(QIODevice::ReadOnly | QIODevice::Text)) {
		QString errMsg = QString(ERR_FILE_OPEN_READ_FAILED_CANNOT_CONTINUE).arg(MAIN_WINDOW_FILE);
		m_outputView.printOutput(errMsg);
		return false;
	}
	QTextStream streamIn(&projectTemplateFileIn);
	QString templateFileContent(streamIn.readAll());
	projectTemplateFileIn.close();

	if (templateFileContent.contains(RESOURCE_FILE_TAG)) {
		QString mainHTMLRelative = m_generatorData.infoPlistValue(KEY_WIDGET_ROOT_DIR) + m_generatorData.infoPlistValue(INFO_PLIST_KEY_MAIN_HTML);
                // OBS mainHTMLRelative = "/" + mainHTMLRelative.mid(m_generatorData.projectDirectory().length());
                mainHTMLRelative = "/" + mainHTMLRelative.mid(m_generatorData.srcDirectory().length());
		templateFileContent.replace(RESOURCE_FILE_TAG, QString("qrc:%1").arg(mainHTMLRelative));
	}

	if (templateFileContent.contains(PANNING_ENABLED_TAG)) {
		templateFileContent.replace(PANNING_ENABLED_TAG, Settings::get(Settings::PanningEnabled).toBool() ? "1" : "0");
	}

	if (templateFileContent.contains(WIDGET_IDENTIFIER_TAG)) {
		templateFileContent.replace(WIDGET_IDENTIFIER_TAG, getWidgetIdentifier());
	}

	QFile mainWindowFileOut(mainWindowFileName);
	if (!mainWindowFileOut.open(QIODevice::WriteOnly | QIODevice::Text)) {
		QString errMsg = QString(ERR_FILE_OPEN_WRITE_FAILED_CANNOT_CONTINUE).arg(MAIN_WINDOW_FILE);
		m_outputView.printOutput(errMsg);
		return false;
	}

	QTextStream streamOut(&mainWindowFileOut);
	streamOut << templateFileContent;
	mainWindowFileOut.close();

	QString msg = QString(MSG_FILE_UPDATED_SUCCESSFULLY).arg(MAIN_WINDOW_FILE);
	m_outputView.printOutput(msg);

	return true;
}

/**
 * Updates .pro files. Currently, the only operation that is done
 * is replacing the @qt_mobility_path tag with the defined mobility
 * path.
 */
bool FileUtilities::updateProjectFile(QString filename)
{
	QFile projectFile(filename);

	if (!projectFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
		// Could not open file for writing -- print error. We don't need the write access
		// yet, but let's check that it's available.
		m_outputView.printOutput(QString(ERR_FILE_OPEN_READ_FAILED_CANNOT_CONTINUE).arg(filename));
		return false;
	}
	else
	{
		// Read file to a variable
		QTextStream streamIn(&projectFile);
		QString fileContent(streamIn.readAll());

		// Replace the parts of file that are required
        if (fileContent.contains(SDK_VERSION_DEFINES_TAG)) {
            // SDK version: full S60 or Nokia Qt SDK (which is a crippled S60)
            fileContent.replace(SDK_VERSION_DEFINES_TAG, Settings::get(Settings::FullS60SDK).toBool() ? "" : "DEFINES += HAVE_NOKIAQTSDK");
		}

		// Reopen and truncate
		projectFile.close();
		projectFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
		QTextStream streamOut(&projectFile);
		streamOut << fileContent;
		projectFile.close();

		// Success, print message to the log
		m_outputView.printOutput(QString(MSG_FILE_UPDATED_SUCCESSFULLY).arg(filename));
		return true;
	}
}

QString FileUtilities::getMainHTMLFileFullPath()
{
	QString path = m_generatorData.infoPlistValue(KEY_WIDGET_ROOT_DIR) + m_generatorData.infoPlistValue(INFO_PLIST_KEY_MAIN_HTML);
	return path;
}

QString FileUtilities::getWidgetIdentifier()
{
	return m_generatorData.infoPlistValue(INFO_PLIST_KEY_IDENTIFIER);
}


QString FileUtilities::findFile(const QDir    & dir,
                                const QString & fileName)
{
    FSTraverseIterator
        fsIt(dir.absolutePath(),
             FSTraverseIterator::DirsPreOrder),
        fsEnd;

    QString
      rv = "";

    for (; fsIt != fsEnd; ++fsIt)
    {
        QFileInfo
            fi = *fsIt;
        QDir
            curDir(fi.absoluteFilePath());
        // if (fi.fileName() == fileName)
        if (curDir.exists(fileName))
        {
            // OBS rv = fi.absoluteFilePath();
            rv = curDir.absolutePath() + QDir::separator() + fileName;
            break;
        }
    }

    return rv;
}



bool FileUtilities::clearUpDir(QDir tmpDir)
{
    bool
        rv = false;

    if (tmpDir.exists())
    {
        FSTraverseIterator
            fsIt(tmpDir.absolutePath(),
                 FSTraverseIterator::Files
                 | FSTraverseIterator::DirsPostOrder),
            fsEnd;

        // directories will be enumerated after all their
        // content has been enumerated

        for (; fsIt != fsEnd; ++fsIt)
        {
            QFileInfo
                fi = *fsIt;
            if (fi.isFile())
            {
                tmpDir.remove(fi.absoluteFilePath());
            }
            else if (fi.isDir())
            {
                if (fi.absolutePath() != tmpDir.absolutePath())
                {
                    tmpDir.rmdir(fi.absolutePath());
                }
            }
        }
    }
    else
    {
        rv = tmpDir.mkpath(tmpDir.absolutePath());
    }

    return rv;
}



bool FileUtilities::syncUnzipWidgetFile(const QString & wgzFile,
                                        const QString & unzipDir)
{
    QFileInfo widgetFileInfo(wgzFile);

    QStringList arguments;
    arguments  << "-xo" << wgzFile << "-d" << unzipDir;


    QProcess
        * process = new QProcess( NULL );
    // ? process->setReadChannelMode(QProcess::MergedChannels);
    // do we need to read output in order to prevent the process
    // from stalling?

    process->start(UNZIP_APP_NAME,
                   arguments);

    process->waitForFinished(-1);

    bool
        rv = process->exitStatus() == QProcess::NormalExit
             && (process->exitCode() == 0);

    delete process;

    return rv;
}


QPair<QString, QString> FileUtilities::sniffAppNames(const QString & widgetFilePath)
{
    QPair<QString, QString>
        rv("", "");

    QFileInfo
        widgetFile(widgetFilePath);

    if (widgetFile.isDir())
    {
        QDir
            widgetDir(widgetFilePath);
        rv.second = widgetDir.dirName();
    }
    else
    {
        QDir
            tmpDir(QDir::tempPath() + "/hybrid");

        bool
            success =  clearUpDir(tmpDir);

        success = syncUnzipWidgetFile(widgetFilePath,
                                      tmpDir.absolutePath());

        if (success)
        {
            QXmlQuery
                xmlQuery;

            QString
                infoPlistPath(findFile(tmpDir, INFO_PLIST_FILE));
            QString
                    xpath = "doc('%1')/descendant::dict/key[text()='DisplayName']/following-sibling::string[1]/child::text()";
            xpath = xpath.arg(infoPlistPath);
            xmlQuery.setQuery(xpath);

            QString
                text;
            success = xmlQuery.evaluateTo(&text);
            if (success)
            {
                rv.second = text.trimmed();
            }
            else
            {
                QString
                    configXmlPath(findFile(tmpDir, W3C_CONFIG_FILE));

                xpath = "doc('%1')/widget/widgetname/child::text()";
                xpath = xpath.arg(configXmlPath);
                xmlQuery.setQuery(xpath);

                success = xmlQuery.evaluateTo(&text);
                if (success)
                {
                    rv.second = text.trimmed();
                }
                else
                {
                    // DEFAULT CASE
                    rv.second = "Hybrid Widget";
                }
            }
        }
    }

    // ??? rv.second += " GeneratedApp";
    rv.first = rv.second.toLower();
    rv.first.replace(" ", "");

    return rv;
}


void FileUtilities::createWidgetResourceFile()
{
        // OBS QString qtResourceFileName(m_generatorData.projectDirectory() + "/" + m_infoPlistFileNameNoSpaces + ".qrc");
    QString
        qtResourceFileName(m_generatorData.srcDirectory()
                           + "/"
                           + m_infoPlistFileNameNoSpaces
                           + ".qrc");

	QDomDocument domDocument;
	QDomElement rccElem = domDocument.createElement(QRC_FILE_TAG_RCC);

	domDocument.appendChild(rccElem);

	QDomElement qresourceElem = domDocument.createElement(QRC_FILE_TAG_QRESOURCE);
	qresourceElem.setAttribute(QRC_FILE_ATTRIBUTE_PREFIX, "/");
	rccElem.appendChild(qresourceElem);

	foreach(const QString &widgetFile, m_generatorData.widgetSrcFiles()) {
		QDomElement fileElement = domDocument.createElement(QRC_FILE_TAG_FILE);
		QDomText newFileName = domDocument.createTextNode(widgetFile);
		fileElement.appendChild(newFileName);
		qresourceElem.appendChild(fileElement);
	}

	QFile qtResourceFile(qtResourceFileName);

	if(qtResourceFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
		QTextStream stream(&qtResourceFile);
		stream << domDocument.toString();
		qtResourceFile.close();
	}

	QString msg = QString(MSG_FILE_CREATED_SUCCESSFULLY).arg(m_infoPlistFileNameNoSpaces+".qrc");
	m_outputView.printOutput(msg);
}

bool FileUtilities::createWidgetProjectFile(const QList< QSharedPointer<HybridPlugin> > &plugins)
{
    // OBS QString qtProjectTemplateFileName(m_generatorData.projectDirectory() + PROJECT_TEMPLATE_FILE);
    QString qtProjectTemplateFileName(m_generatorData.srcDirectory() + PROJECT_TEMPLATE_FILE);

    QString templateFileContent;
    QString errMsg = QString(ERR_FILE_OPEN_READ_FAILED_CANNOT_CONTINUE).arg(qtProjectTemplateFileName);
    if (!readTemplateFile(qtProjectTemplateFileName, templateFileContent, errMsg))
        return false;

    /// START CONTENT REPLACE

    // TODO: replace this whole class with the filecopier utility

    if (templateFileContent.contains(SDK_VERSION_DEFINES_TAG)) {
        templateFileContent.replace(SDK_VERSION_DEFINES_TAG, Settings::get(Settings::FullS60SDK).toBool() ? "" : "DEFINES += HAVE_NOKIAQTSDK");
    }

    if (templateFileContent.contains(TOOL_NAME_TAG)){
        templateFileContent.replace(TOOL_NAME_TAG, TOOL_NAME_STRING);
    }

    if (templateFileContent.contains(TIMSTAMP_TAG)) {
        templateFileContent.replace(TIMSTAMP_TAG, QDateTime::currentDateTime().toString(Qt::SystemLocaleShortDate));
    }

    if (templateFileContent.contains(APPLICATION_NAME_TAG)) {
        templateFileContent.replace(APPLICATION_NAME_TAG, m_generatorData.infoPlistValue(INFO_PLIST_KEY_DISPLAY_NAME));
    }

    if (templateFileContent.contains(RESOURCE_FILE_TAG)) {
        templateFileContent.replace(RESOURCE_FILE_TAG, m_infoPlistFileNameNoSpaces + ".qrc\n");
    }

    // Set plugin deployment directives
    if (templateFileContent.contains(PLUGIN_DEPLOYMENT_TAG)) {
        QString deployment;
        foreach (QSharedPointer<HybridPlugin> plugin, plugins)
        {
            if (plugin->selectedPlatform())
            {
                deployment += plugin->symbianDeploymentString(m_generatorData.isRemotelyCompiled());
            }
        }
        templateFileContent.replace(PLUGIN_DEPLOYMENT_TAG, deployment);
    }

    // UID3
    if (templateFileContent.contains(SYMBIAN_UID3_TAG)) {
        if (!Settings::get(Settings::UID3).toString().isEmpty()) {
            templateFileContent.replace(SYMBIAN_UID3_TAG, "TARGET.UID3 = " + Settings::get(Settings::UID3).toString());
        } else {
            templateFileContent.replace(SYMBIAN_UID3_TAG, "");
        }
    }

    /// END CONTENT REPLACE

	QString plainProjectFileName = m_infoPlistFileNameNoSpaces+".pro";
        // OBS QString qtProjectFileName(m_generatorData.projectDirectory() + "/" + plainProjectFileName);
        QString
            qtProjectFileName(m_generatorData.srcDirectory()
                              + "/"
                              + plainProjectFileName);

	QFile proFile(qtProjectFileName);
	if(proFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QTextStream stream(&proFile);
        stream << templateFileContent;

		QString msg = QString(MSG_FILE_CREATED_SUCCESSFULLY).arg(plainProjectFileName);
		m_outputView.printOutput(msg);
	}
	else {
		QString errMsg = QString(ERR_FILE_OPEN_WRITE_FAILED_CANNOT_CONTINUE).arg(qtProjectFileName);
		m_outputView.printOutput(errMsg);
		return false;
	}

	// remove the template file
	QFile::remove(qtProjectTemplateFileName);

	return true;
}

bool FileUtilities::createPluginsProjectFile(const QList< QSharedPointer<HybridPlugin> > &plugins)
{
    QString pluginsProjectContent;
    foreach (QSharedPointer<HybridPlugin> plugin, plugins)
    {
        if (plugin->selectedPlatform())
        {
            qDebug() << "Plugin" << plugin->name() << "is selected, updating compilation list";
            if (plugin->selectedPlatform()->format() == HybridPluginPlatform::Source)
            {
                // Add the plugin to the plugins compilation list
                pluginsProjectContent += plugin->name() + " \\\n";

                // Prepare project file
                QString pluginProjectFile = m_generatorData.mwDirectory() + plugin->name() + "/" + plugin->name() + ".pro";
                if (!QFile::exists(pluginProjectFile))
                {
                    // Plugin project file does not exist. Project file has to have a
                    // same name as the directory -- qmake assumes so.
                    m_outputView.printOutput("Could not find .pro file for plugin " + plugin->name() + "!");
                    return false;
                }
                else
                {
                    bool success = updateProjectFile(pluginProjectFile);
                    if (!success)
                    {
                        // If project file update failed, the build process
                        // won't be able to complete, so we should fail
                        // already here.
                        return false;
                    }
                }
            }
        }
    }

    // Create the plugins project file
    QString fileName = m_generatorData.mwDirectory() + PLUGINS_PROJECT_FILE;
    QFile pluginsProjectFile(fileName);
    if (pluginsProjectFile.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        QTextStream stream(&pluginsProjectFile);
        stream << QString(PLUGINS_PROJECT_FILE_CONTENT).arg(pluginsProjectContent);
        pluginsProjectFile.close();
        m_outputView.printOutput(QString(MSG_FILE_CREATED_SUCCESSFULLY).arg(PLUGINS_PROJECT_FILE));
    }
    else
    {
        m_outputView.printOutput(QString(ERR_FILE_OPEN_WRITE_FAILED_CANNOT_CONTINUE).arg(fileName));
        return false;
    }

	return true;
}

bool FileUtilities::configXmlToInfoPlistFile(WidgetType widgetType)
{

	QMap<QString, QString> &configXmlData = m_generatorData.configXmlData();

        // OBS QString templateFullFileName = m_generatorData.projectDirectory() + INFO_PLIST_FILE;
        QString
            templateFullFileName = m_generatorData.srcDirectory() + INFO_PLIST_FILE;
	QString templateFileContent;
	QString errMsg = QString(ERR_FILE_OPEN_READ_FAILED_CANNOT_CONTINUE).arg(templateFullFileName);
    if (!readTemplateFile(templateFullFileName, templateFileContent, errMsg))
		return false;

    if (widgetType == OPERA_WIDGET)
    {
		templateFileContent.replace(INFO_PLIST_DISPLAY_NAME_TAG, configXmlData.value("widget.widgetname:", "OperaWidget"));
		templateFileContent.replace(INFO_PLIST_IDENTIFIER_TAG, configXmlData.value("widget.id.host:", "www.default.identifier"));
		templateFileContent.replace(INFO_PLIST_MAIN_HTML_TAG, W3C_MAIN_HTML_FILE);
	}
    else if(widgetType == W3C_WIDGET)
    {
		templateFileContent.replace(INFO_PLIST_DISPLAY_NAME_TAG, configXmlData.value("widget.name:", "W3CWidget"));
		templateFileContent.replace(INFO_PLIST_IDENTIFIER_TAG, configXmlData.value("widget:id", "www.default.identifier"));
		templateFileContent.replace(INFO_PLIST_MAIN_HTML_TAG, configXmlData.value("widget.content:src", "index.html"));
	}
	templateFileContent.replace(INFO_PLIST_VERSION_TAG, "1.0.0");

	QString infoPlistFullFileName = m_generatorData.widgetDirectory() + INFO_PLIST_FILE;
	QFile infoPlistFileOut(infoPlistFullFileName);
	if(!infoPlistFileOut.open(QIODevice::WriteOnly | QIODevice::Text)) {
		QString errMsg = QString(ERR_FILE_OPEN_WRITE_FAILED_CANNOT_CONTINUE).arg(infoPlistFullFileName);
		m_outputView.printOutput(errMsg);
		return false;
	}
	QTextStream streamOut(&infoPlistFileOut);
	streamOut << templateFileContent;
	infoPlistFileOut.close();

	QString msg = QString(MSG_FILE_CREATED_SUCCESSFULLY).arg(INFO_PLIST_FILE);
	m_outputView.printOutput(msg);

	// remove the template file
	QFile::remove(templateFullFileName);

	QString srcDir = m_generatorData.widgetDirectory();
	QString destDir;
	if(widgetType == OPERA_WIDGET)
		destDir = m_generatorData.widgetDirectory() + configXmlData.value("widget.widgetname;", "OperaWidget") + "/";
	else
		destDir = m_generatorData.widgetDirectory() + configXmlData.value("widget.name;", "W3CWidget") + "/";
	DirectoryUtilities dirUtil(m_outputView, m_generatorData);

	m_outputView.printOutput("OPERA1: " + srcDir);
	m_outputView.printOutput("OPERA2: " + destDir);

	return dirUtil.copyDirectory(srcDir, destDir, true);
}

/**
 * Creates a info.plist file for directories that do not contain one. Such
 * directory could be created by wget using the remote generator.
 */
bool FileUtilities::directoryToInfoPlistFile()
{
	// Find the name of the main HTML file. The directory may contains several
	// HTML files with arbitraty names, so detecting the right one may be a bit tricky.
	// TODO: this won't detect HTML files from subdirs
	m_outputView.printOutput("Preparing info.plist from directory contents");
	QStringList fileList = QFileInfo(m_generatorData.widgetDirectory()).dir().entryList(QDir::Files | QDir::Readable);
	QStringList htmlFiles;
	QString indexFile = "";
	foreach (QString file, fileList)
	{
		QRegExp rx;
		rx.setPattern("^(.*)\\.(htm|html)$");
		if (rx.indexIn(file) != -1)
		{
			if (rx.cap(1) == "index" || rx.cap(1) == "main")
			{
				// Main file found
				indexFile = file;
			}
			else
			{
				// Not a definite main file
				htmlFiles.append(file);
			}
		}
	}

	if (indexFile.isEmpty() && htmlFiles.count() > 0)
	{
		// For now, we'll just grab the first HTML
		// file if there was not a good candidate
		indexFile = htmlFiles.at(0);
	}

	if (indexFile.isEmpty())
	{
		m_outputView.printOutput("Appropriate main HTML file was not found!");
		return false;
	}
	else
	{
		m_outputView.printOutput("Using " + indexFile + " as the main HTML file");
        // OBS QString templateFullFileName = m_generatorData.projectDirectory() + INFO_PLIST_FILE;
        QString
            templateFullFileName = m_generatorData.srcDirectory() + INFO_PLIST_FILE;
		QString templateFileContent;
		QString errMsg = QString(ERR_FILE_OPEN_READ_FAILED_CANNOT_CONTINUE).arg(templateFullFileName);

		// Read template file contents to a variable
		if (!readTemplateFile(templateFullFileName, templateFileContent, errMsg))
			return false;

		templateFileContent.replace(INFO_PLIST_DISPLAY_NAME_TAG, m_generatorData.widgetFileName());
		templateFileContent.replace(INFO_PLIST_IDENTIFIER_TAG, m_generatorData.widgetFileName());
		templateFileContent.replace(INFO_PLIST_MAIN_HTML_TAG, indexFile);
		templateFileContent.replace(INFO_PLIST_VERSION_TAG, "1.0.0");

		// Try to open info.plist file for writing
		QString infoPlistFullFileName = m_generatorData.widgetDirectory() + INFO_PLIST_FILE;
		QFile infoPlistFileOut(infoPlistFullFileName);
		if (!infoPlistFileOut.open(QIODevice::WriteOnly | QIODevice::Text)) {
			m_outputView.printOutput(QString(ERR_FILE_OPEN_WRITE_FAILED_CANNOT_CONTINUE).arg(infoPlistFullFileName));
			return false;
		}

		// Write info.plist contents
		QTextStream streamOut(&infoPlistFileOut);
		streamOut << templateFileContent;
		infoPlistFileOut.close();

		// Print success note
		m_outputView.printOutput(QString(MSG_FILE_CREATED_SUCCESSFULLY).arg(INFO_PLIST_FILE));

		// remove the template file
		QFile::remove(templateFullFileName);

		return true;
	}
}

bool FileUtilities::readTemplateFile(const QString &fileName, QString &fileContent, const QString &onErrorMessage)
{
	QFile templateFile(fileName);
	if (!templateFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
		m_outputView.printOutput(onErrorMessage);
		return false;
	}
	QTextStream stream(&templateFile);
	fileContent = stream.readAll();
	return true;
}
